/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package model.dao;

import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import model.pojo.Turma;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;
import model.dao.exceptions.NonexistentEntityException;
import model.pojo.Professor;

/**
 *
 * @author Filipe
 */
public class ProfessorJpaController implements ProfessorInterface {

    public ProfessorJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    @Override
    public void create(Professor professor) {
        if (professor.getTurma() == null) {
            professor.setTurma(new ArrayList<Turma>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Collection<Turma> attachedTurma = new ArrayList<Turma>();
            for (Turma turmaTurmaToAttach : professor.getTurma()) {
                turmaTurmaToAttach = em.getReference(turmaTurmaToAttach.getClass(), turmaTurmaToAttach.getId());
                attachedTurma.add(turmaTurmaToAttach);
            }
            professor.setTurma(attachedTurma);
            em.persist(professor);
            for (Turma turmaTurma : professor.getTurma()) {
                Professor oldProfessorOfTurmaTurma = turmaTurma.getProfessor();
                turmaTurma.setProfessor(professor);
                turmaTurma = em.merge(turmaTurma);
                if (oldProfessorOfTurmaTurma != null) {
                    oldProfessorOfTurmaTurma.getTurma().remove(turmaTurma);
                    oldProfessorOfTurmaTurma = em.merge(oldProfessorOfTurmaTurma);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    @Override
    public void edit(Professor professor) throws NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Professor persistentProfessor = em.find(Professor.class, professor.getId());
            Collection<Turma> turmaOld = persistentProfessor.getTurma();
            Collection<Turma> turmaNew = professor.getTurma();
            Collection<Turma> attachedTurmaNew = new ArrayList<Turma>();
            for (Turma turmaNewTurmaToAttach : turmaNew) {
                turmaNewTurmaToAttach = em.getReference(turmaNewTurmaToAttach.getClass(), turmaNewTurmaToAttach.getId());
                attachedTurmaNew.add(turmaNewTurmaToAttach);
            }
            turmaNew = attachedTurmaNew;
            professor.setTurma(turmaNew);
            professor = em.merge(professor);
            for (Turma turmaOldTurma : turmaOld) {
                if (!turmaNew.contains(turmaOldTurma)) {
                    turmaOldTurma.setProfessor(null);
                    turmaOldTurma = em.merge(turmaOldTurma);
                }
            }
            for (Turma turmaNewTurma : turmaNew) {
                if (!turmaOld.contains(turmaNewTurma)) {
                    Professor oldProfessorOfTurmaNewTurma = turmaNewTurma.getProfessor();
                    turmaNewTurma.setProfessor(professor);
                    turmaNewTurma = em.merge(turmaNewTurma);
                    if (oldProfessorOfTurmaNewTurma != null && !oldProfessorOfTurmaNewTurma.equals(professor)) {
                        oldProfessorOfTurmaNewTurma.getTurma().remove(turmaNewTurma);
                        oldProfessorOfTurmaNewTurma = em.merge(oldProfessorOfTurmaNewTurma);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = professor.getId();
                if (findProfessor(id) == null) {
                    throw new NonexistentEntityException("The professor with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    @Override
    public void destroy(Integer id) throws NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Professor professor;
            try {
                professor = em.getReference(Professor.class, id);
                professor.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The professor with id " + id + " no longer exists.", enfe);
            }
            Collection<Turma> turma = professor.getTurma();
            for (Turma turmaTurma : turma) {
                turmaTurma.setProfessor(null);
                turmaTurma = em.merge(turmaTurma);
            }
            em.remove(professor);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    @Override
    public List<Professor> findProfessorEntities() {
        return findProfessorEntities(true, -1, -1);
    }

    @Override
    public List<Professor> findProfessorEntities(int maxResults, int firstResult) {
        return findProfessorEntities(false, maxResults, firstResult);
    }

    private List<Professor> findProfessorEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select object(o) from Professor as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
       /**
     * @return retorna o professor relativo ao nome passado como parametro
     */
    public Integer findNDisciplina(String nome, String disciplina) {
        Integer i = 0;
        List<Professor> listaProfessor = findProfessorEntities();
        for (Professor item : listaProfessor) {
            if (item.getNome().equals(nome)) {
                List<Turma> turma = (List<Turma>) item.getTurma();
                if (!turma.isEmpty()) {
                    for (Turma turm : turma) {
                        if (turm.getDisciplina().getNome().equals(disciplina)) {
                            i++;
                        }
                    }
                }
            }
        }
        return i;
    }

    /**
     * @return retorna o numero de turmas ja lecionadas por determinado
     * professor
     */
    public Integer findNumerTurm(String nome) {
        List<Professor> listaProfessor = findProfessorEntities();
        for (Professor item : listaProfessor) {
            if (item.getNome().equals(nome)) {
                return item.getTurma().size() + 1;
            }
        }
        return 0;
    }

    @Override
    public Professor findProfessor(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Professor.class, id);
        } finally {
            em.close();
        }
    }

    /**
     * @return retorna professor que possui CPF referente ao passado como
     * parametro
     */
    public Professor findCpf(String CPF) {
        List<Professor> listaProfessor = findProfessorEntities();
        for (Professor item : listaProfessor) {
            if (item.getCpf().equals(CPF)) {
                return item;
            }
        }
        return null;
    }

    public int getProfessorCount() {
        EntityManager em = getEntityManager();
        try {
            Query q = em.createQuery("select count(o) from Professor as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

    @Override
    public boolean existeProfessor(String cpf) {
        EntityManager em = getEntityManager();
        try {
            if (em.createQuery("Select cpf from Professor where cpf = '" + cpf + "'").getResultList().isEmpty()) {
                return false;
            } else {
                return true;
            }
        } finally {
            em.close();
        }
    }
}
